[网络流24题]软件补丁问题

2020-02-01
网络流24题

题意

电脑一开始有$n$个病毒,现在有$m$个补丁可以使用

每个补丁只有在当前电脑包含某些病毒并不包含某些病毒时才能生效,它会消除某些错误并带入新的错误

每个补丁有消耗的时间,求最小时间消除所有病毒

题解

病毒数量很小$(n\leq 20)$,直接把病毒有无装压,作为图中节点;补丁视为边,炮最短路即可

你问我为什么这题在网络流24题里?

夫妻肺片里应该没有二位吧

调试记录

priority_queue 默认大根

vis数组开小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>
const int INF = 0x3f3f3f3f;
using namespace std;
int n, m, b[2][105], f[2][105], t[105];
char s[25]; int dis[(1 << 21)]; bool vis[(1 << 21)];
void Dijkstra(int S){
priority_queue <pair<int, int> > q; while (!q.empty()) q.pop(); q.push(make_pair(0, S));
memset(dis, 0x3f, sizeof dis); dis[S] = 0;
while (!q.empty()){
int cur = q.top().second; q.pop();
if (vis[cur]) continue;
vis[cur] = 1;
for (int i = 1; i <= m; i++){
if ((cur & b[0][i]) == b[0][i] && (cur & b[1][i]) == 0){
int v = ((cur | f[0][i]) | f[1][i]) ^ f[0][i];
if (dis[v] > dis[cur] + t[i]){
dis[v] = dis[cur] + t[i];
if (!vis[v]) q.push(make_pair(-dis[v], v));
}
}
}
}
}
int main(){
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++){
scanf("%d%s", t + i, s);
for (int j = 0; j < n; j++)
if (s[j] == '+') b[0][i] += (1 << j);
else if (s[j] == '-') b[1][i] += (1 << j);
scanf("%s", s);
for (int j = 0; j < n; j++)
if (s[j] == '-') f[0][i] += (1 << j);
else if (s[j] == '+') f[1][i] += (1 << j);
}
Dijkstra((1 << n) - 1);
if (dis[0] == INF) puts("0");
else printf("%d\n", dis[0]);
return 0;
}